<template>
  <!-- tablecommon -->
  <div class="commonBoxmp white-bg">
    <div class="fd HeightAuto">
      <div id="searchAntX6"></div>
      <div class="containerAntX6">
        <div class="jcb aic">
          <div class="aic" style="padding-bottom: 15px">
            <!-- 撤回 前进 -->
            <el-button
              @click="handleback"
              type="primary"
              :disabled="state.canRedo"
            >
              <el-icon class="white"><back /></el-icon>
            </el-button>
            <el-button
              @click="handleright"
              type="primary"
              :disabled="state.canUndo"
            >
              <el-icon class="white"><right /></el-icon>
            </el-button>

            <!-- 撤回 前进 -->
            <el-button type="success" @click="handleSaveData"
              >保存数据</el-button
            >
            <el-button
              type="danger"
              @click="handleDeleteCell"
              :disabled="state.selectCan"
              >删除选中</el-button
            >

            <el-dropdown class="mx15" @command="handleCommand">
              <el-button type="primary">
                导出图片<el-icon class=""><arrow-down /></el-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="SVG">导出SVG</el-dropdown-item>
                  <el-dropdown-item command="PNG">导出PNG</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
          <div class="">
            <el-popover
              placement="left-start"
              title="介绍"
              :width="200"
              trigger="hover"
            >
              <template #reference>
                <el-icon size="25"><question-filled /></el-icon>
              </template>
              <p>按下ctrl键 可以拖拽</p>
              <p>鼠标选取后 按下 deltet 可以删除</p>
            </el-popover>
          </div>
        </div>
        <div class="w100" id="containerAntX6"></div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted } from "vue";
import { useRouter, useRoute } from "vue-router";
import {
  Addon,
  Graph,
  Shape,
  DataUri,
  Model,
  Cell,
  EdgeView,
  Vector,
} from "@antv/x6";
import { ElMessage, ElMessageBox } from "element-plus";
const { Rect, Circle, Edge } = Shape;
const router = useRouter();
const route = useRoute();

/*
基本数据类型
引用数据类型（复杂类型） 个人建议 ref初始化变量 
ref 和 reactive 本质我们可以简单的理解为ref是对reactive的二次包装, 
ref定义的数据访问的时候要多一个.value
*/
const count = ref(0);
const state: any = reactive({
  selectCan: true,
  graph: null,
  options: {
    useLocalStorage: true,
    offset: 30,
  },
  history: Graph.HistoryManager,
  canRedo: true,
  canUndo: true,
});
onUnmounted(() => {
  //卸载 清空数据
  state.graph.dispose();
});
onMounted(() => {
  setTimeout(() => {
    const HeightAutoDom: any = document.querySelector(".containerAntX6");
    let height = HeightAutoDom.offsetHeight - 85;
    getInit(height);
  }, 500);
});
/**
 * 撤回
 */
const handleback = () => {
  state.history.undo();
};
/**
 * 向右前进
 */
const handleright = () => {
  state.history.redo();
};
/**
 * 保存数据
 */
const handleSaveData = () => {
  ElMessage.success("保存成功");
  localStorage.setItem("antV", JSON.stringify(state.graph.toJSON()));
};
//
/**
 * 图片功能按钮
 */
const handleCommand = (type: string) => {
  switch (type) {
    case "SVG":
      state.graph.toSVG((dataUri: string) => {
        // 下载
        DataUri.downloadDataUri(DataUri.svgToDataUrl(dataUri), "chart.svg");
      });
      break;

    case "PNG":
      state.graph.toPNG((dataUri: string) => {
        // 下载
        DataUri.downloadDataUri(dataUri, "chart.png");
      });
      break;
  }
};

const getInit = (num: number) => {
  state.graph = new Graph({
    history: {
      enabled: true,
    },
    snapline: {
      //是否有对齐线
      enabled: true,
      sharp: true,
    },
    mousewheel: {
      //画布缩放
      enabled: true,
      modifiers: ["ctrl", "meta"],
    },
    scroller: {
      //是否可以滚动
      enabled: true,
      pageVisible: false,
      pageBreak: false,
      pannable: true,
      modifiers: "ctrl",
    },
    clipboard: {
      //开启粘贴板
      enabled: true,
      useLocalStorage: true,
    },
    keyboard: {
      enabled: true, //开启键盘监听
      global: true,
    },
    selecting: {
      //是否可以选择节点
      enabled: true,
      rubberband: true,
      // showNodeSelectionBox: true,
    },
    resizing: true, //开启可以改变尺寸大小
    container: document.getElementById("containerAntX6"),
    height: num,
    background: {
      color: "#FFF", // 设置画布背景颜色
    },
    grid: {
      size: 10, // 网格大小 10px
      visible: true, // 渲染网格背景
      type: "doubleMesh",
      args: [
        {
          color: "#eee", // 主网格线颜色
          thickness: 1, // 主网格线宽度
        },
        {
          color: "#ddd", // 次网格线颜色
          thickness: 1, // 次网格线宽度
          factor: 4, // 主次网格线间隔
        },
      ],
    },
    rotating: {
      //开启组件旋转
      enabled: true,
    },
    //连接线
    connecting: {
      snap: true, //自动吸附
      router: {
        name: "manhattan",
        args: {
          strokeDasharray: "5 5",
          startDirections: ["bottom"],
          endDirections: ["top"],
        },
      },
    },
    //     attrs:{
    //           line: {
    //     stroke: '#1890ff',
    //     strokeDasharray: 2,
    //     targetMarker: 'classic',
    //     style: {
    //       animation: 'ant-line 30s infinite linear',
    //     },
    //   },
    //  }
  });
  /**
   * 撤销 前进
   *
   */
  state.history = state.graph.history;
  state.history.on("change", () => {
    state.canRedo = state.history.canRedo();
    state.canUndo = state.history.canUndo();
  });
  const stencil = new Addon.Stencil({
    target: state.graph,
    title: "组件",
    stencilGraphWidth: 300,
    stencilGraphHeight: 200,
    search(cell, keyword) {
      return cell.shape.indexOf(keyword) !== -1;
    },
    placeholder: "Search by shape name",
    notFoundText: "Not Found",
    collapsable: true,
    groups: [
      {
        name: "group1",
        title: "文本框",
      },
      {
        name: "group2",
        title: "按钮",
      },
      // {
      //   name: "group3",
      //   title: "引导",
      // },
    ],
  });

  let text = new Rect({
    width: 120,
    height: 80,
    attrs: {
      rect: { fill: "#31D0C6", stroke: "#4B4A67", strokeWidth: 2 },
      text: { text: "文本框", fill: "white" },
    },
    tools: ["button-remove", "boundary"],
    ports: {
      groups: {
        group1: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "left",
          },
        },
        group2: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "right",
          },
        },
        group3: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "top",
          },
        },
        group4: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "bottom",
          },
        },
      },
      items: [
        {
          id: "port1",
          group: "group1",
        },
        {
          id: "port2",
          group: "group2",
        },
        {
          id: "port3",
          group: "group3",
        },
        {
          id: "port4",
          group: "group4",
        },
      ],
    },
  });

  const edge = new Edge({
    source: [80, 160],
    target: [480, 160],
    attrs: {
      line: {
        sourceMarker: "block",
        targetMarker: "block",
      },
    },
  });
  const btn = new Circle({
    width: 60,
    height: 60,
    tools: ["button-remove", "boundary"],
    attrs: {
      circle: { fill: "#FE854F", strokeWidth: 2, stroke: "#4B4A67" },
      text: { text: "按钮", fill: "white" },
    },
    ports: {
      groups: {
        group1: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "left",
          },
        },
        group2: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "right",
          },
        },
        group3: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "top",
          },
        },
        group4: {
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: "#31d0c6",
              strokeWidth: 2,
              fill: "#fff",
            },
            text: {
              fontSize: 12,
              fill: "#888",
            },
          },
          position: {
            name: "bottom",
          },
        },
      },
      items: [
        {
          id: "port1",
          group: "group1",
        },
        {
          id: "port2",
          group: "group2",
        },
        {
          id: "port3",
          group: "group3",
        },
        {
          id: "port4",
          group: "group4",
        },
      ],
    },
  });
  stencil.load([text], "group1");
  stencil.load([btn], "group2");
  document.getElementById("searchAntX6")?.appendChild(stencil.container);
  //赋值
  state.graph.bindKey("ctrl+c", () => {
    const cells = state.graph.getSelectedCells();
    if (cells.length) {
      state.graph.copy(cells);
    }
    return false;
  });
  //粘贴
  state.graph.bindKey("ctrl+v", () => {
    if (!state.graph.isClipboardEmpty()) {
      const cells = state.graph.paste({ offset: 32 });
      state.graph.cleanSelection();
      state.graph.select(cells);
    }
    return false;
  });

  /**
   * 单击事件
   */
  state.graph.on("blank:click", () => {
    reset();
    state.selectCan = true;
  });
  /**
   * 选中事件
   */
  state.graph.on(
    "cell:selected",
    (args: { cell: Cell; options: Model.SetOptions }) => {
      // code here
      reset();
      state.selectCan = false;
    },
  );
  //删除选择区域
  state.graph.bindKey("del", () => {
    let data = state.graph.getSelectedCells();
    state.graph.model.removeCells(data);
  });
  /**
   * 双击线进行编辑备注
   */
  state.graph.on("cell:dblclick", ({ cell, e }) => {
    cell.addTools([
      {
        name: cell.isEdge() ? "edge-editor" : "node-editor",
        args: {
          event: e,
        },
      },
    ]);
  });
  /**
   * 工作流
   */
  work();
  /**
   * 导入数据
   */
  state.graph.fromJSON(JSON.parse(localStorage.getItem("antV") as string));
  //   state.graph.fromJSON([
  //   {
  //     id: 'node1',
  //     x: 40,
  //     y: 40,
  //     width: 100,
  //     height: 40,
  //     label: 'Hello',
  //     shape: 'rect',
  //   },
  //   {
  //     id: 'node2',
  //     x: 40,
  //     y: 40,
  //     width: 100,
  //     height: 40,
  //     label: 'Hello',
  //     shape: 'ellipse',
  //   },
  //   {
  //     id: 'edge1',
  //     source: 'node1',
  //     target: 'node2',
  //     shape: 'edge',
  //   }
  // ])

  /**
   * 选中边
   */

  function reset() {
    const edges = state.graph.getEdges();
    edges.forEach((edge) => {
      edge.attr("line/stroke", "black");
      edge.prop("labels/0", {
        attrs: {
          body: {
            stroke: "black",
          },
        },
      });
    });
  }
  state.graph.on("edge:click", ({ edge }) => {
    state.selectCan = false;
    reset();
    edge.attr("line/stroke", "red");
    edge.prop("labels/0", {
      attrs: {
        body: {
          stroke: "orange",
        },
      },
    });
  });
};
/**
 * 删除选中
 */
const handleDeleteCell = () => {
  let data = state.graph.getSelectedCells();
  state.graph.model.removeCells(data);
};
/**
 * 工作流动画
 */
const work = () => {
  state.graph.on("signal", (cell: Cell) => {
    if (cell.isEdge()) {
      const view = state.graph.findViewByCell(cell) as EdgeView;
      if (view) {
        const token = Vector.create("circle", { r: 6, fill: "#feb662" });
        const target = cell.getTargetCell();
        setTimeout(() => {
          view.sendToken(token.node, 1000, () => {
            if (target) {
              state.graph.trigger("signal", target);
            }
          });
        }, 300);
      }
    } else {
      flash(cell);
      const edges = state.graph.model.getConnectedEdges(cell, {
        outgoing: true,
      });
      edges.forEach((edge: Cell) => state.graph.trigger("signal", edge));
    }
  });
  state.graph.on("node:mousedown", ({ cell }) => {
    // manual = true
    state.graph.trigger("signal", cell);
  });
};
const flash = (cell: Cell) => {
  const cellView = state.graph.findViewByCell(cell);
  if (cellView) {
    cellView.highlight();
    setTimeout(() => cellView.unhighlight(), 300);
  }
};
//   let manual = false
// const trigger = () => {
//   state.graph.trigger('signal', a)
//   if (!manual) {
//     setTimeout(trigger, 5000)
//   }
// }
</script>

<style scoped lang="scss">
#searchAntX6 {
  position: relative;
  background-color: rgb(242, 242, 242);
  padding: 25px;
  width: 300px;
}
.containerAntX6 {
  width: calc(100% - 300px);
  height: calc(100% - 0px);
  padding: 15px;
  box-shadow: 3px 3px 6px #888;
  margin-left: 15px;
  overflow: hidden;
  background-color: #f2f2f2;
}

#containerAntX6 {
  // margin: 15px;
}
</style>
